/*
 * Copyright 2008 Federal Emergency Management Agency
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0 
 *    
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 *  
 */
package gov.fema.hazus.bdc.server.servlet;

import gov.fema.hazus.bdc.client.common.UserQuery;
import gov.fema.hazus.bdc.client.common.UserResults;
import gov.fema.hazus.bdc.client.services.ServerException;
import gov.fema.hazus.bdc.client.services.UserService;
import gov.fema.hazus.bdc.shared.entity.User;

import java.util.ArrayList;
import java.util.Iterator;

import org.apache.log4j.Logger;

import com.google.appengine.api.datastore.FetchOptions;
import com.google.inject.Singleton;
import com.googlecode.objectify.OQuery;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;

@Singleton
public class UserServlet implements UserService {

	private static final long serialVersionUID = -5423791774700166905L;
	private final Logger logger = Logger.getLogger(BuildingServlet.class);

	private DAO dao = new DAO();
	
	public UserServlet()
    {
        
    }

	public void deleteUsers(ArrayList<User> users) throws ServerException {
		
		/*
		 * users in the list only have IDs, nothing else,
		 * so we need to delete by ID
		 */
		try {
			
			for (Iterator iterator = users.iterator(); iterator.hasNext();) {
				User u = (User) iterator.next();
				Long id = u.getId();
				User user = dao.ofy().get(User.class, id);
				dao.ofy().delete(user);
			}
		} catch (Exception e) {
			//TODO: warn user we could not delete
		}
	}

	public UserResults find(UserQuery userQuery) throws ServerException {

		UserResults results = new UserResults();
		
		// get total building
		UserStatistics stats = new UserStatistics();
	    int totalUsers = stats.getCount();
		results.setTotal(totalUsers);
	    
		// looks like client prefers to get total from the query, not results
		userQuery.setTotal(totalUsers);
		
		results.setUserQuery(userQuery);
		
		int offset = userQuery.getNext();
		int limit = userQuery.getMax();
		
		Objectify ofy = ObjectifyService.begin();
		OQuery<User> q = ObjectifyService.createQuery(User.class);
		q.sort("username"); // ascending sort on username
		ArrayList<User> users = (ArrayList<User>) ofy.prepare(q).asList(FetchOptions.Builder.withLimit(limit).offset(offset));
		
		results.setUsers(users);
		
		return results;
	}

	public User getUser(User user) throws ServerException {

		logger.debug("get user for editing:" + user);
		
		Objectify ofy = ObjectifyService.begin();
		OQuery<User> q = ObjectifyService.createQuery(User.class);
		q.sort("username"); // ascending sort on building name
		q.filter("id == ", user.getId());
		User fetched = (User) ofy.prepare(q).asSingle();
		
		return fetched;
	}

	public UserResults getUsers() throws ServerException {
		// TODO Auto-generated method stub
		return null;
		
	}

	public User save(User user) throws ServerException {
		
		if( user.getId() == null)
		{
			saveNewUser(user);
		}
		
		validateUser(user);
		
		dao.ofy().put(user);
		
		return user;
	}

	private void validateUser(User user) throws ServerException {
		if( user.getUsername() == null 
				|| user.getUsername().equalsIgnoreCase("")
				|| user.getUsername().matches("^\\s+$"))
		{
			throw new ServerException("A user name is required");
		}
		
		// and, we can't have people creating another superadmin
		// because that is a reserved name
		if( user.getUsername().equalsIgnoreCase("superadmin"))
		{
			throw new ServerException("The username 'superadmin' is reserved.");
		}
		
	}

	private void saveNewUser(User user) throws ServerException {
		
		logger.debug("saving new user");
		validateUser(user);		
		dao.ofy().put(user);
		
		// user now has ID
		
	}
    
}
